#ifndef _IndexOptr
#define _IndexOptr

#include <cassert>
#include <cmath>
#include <exception>

#define ELEMENT_SIZE	20

class OutOfBoundaryException : public std::range_error{
/*private:
	std::string _message;
public:
	OutOfBoundaryException() : _message(std::string.empty()){}
	OutOfBoundaryException(std::string message) : _message(message){}
	const char* what() const throw{
		return _message.c_str();
	}*/
public:
	// OutOfBoundaryException() : this(""){}
	OutOfBoundaryException(std::string message = "") : std::range_error(message){}
};

class IndexOptr{
public:
	int *ele;
	size_t size;
public:
	IndexOptr(){
		size = ELEMENT_SIZE;
		ele = new int[ELEMENT_SIZE];
		for(int i = 1; i <= ELEMENT_SIZE; i++){
			// *(ele + i) = pow(2.0, i + 1) - 1;		
			*(ele + i - 1) = (1 << i) - 1;
		}
	}

	int& operator[](const size_t);
	const int& operator[](const size_t) const;
};

int& IndexOptr::operator[](const size_t index){
	// assert(index < size);
	if(index >= size)
		throw OutOfBoundaryException("Out of boundary");
		// throw OutOfBoundaryException("Out of boundary"); // Should use OutOfBoundaryException* in catch clause.
	return ele[index];
}


const int& IndexOptr::operator[](const size_t index) const{
	// assert(index < size);
	return ele[index];
}


#endif // _IndexOptr